/************************************************************************

								Heroes IV
					  Copyright 2000, The 3DO Company

	------------------------------------------------------------------
  						     campaign_file_header.h

	$Header: /game/campaign_file_header.h $

	$NoKeywords: $

 ************************************************************************/

#if !defined( CAMPAIGN_FILE_HEADER_H_INCLUDED )
#define CAMPAIGN_FILE_HEADER_H_INCLUDED

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

#include <memory>
#include <streambuf>
#include <string>
#include <vector>

#include "campaign_file_ref.h"
#include "counted_ptr.h"
#include "owned_ptr.h"
#include "shared_ptr.h"
#include "uncopyable.h"

class t_campaign_file_header;
class t_map_header;
class t_multi_scenario_campaign_file_header;
class t_progress_handler;
class t_single_scenario_campaign_file_header;

typedef t_counted_ptr< t_campaign_file_header > t_campaign_file_header_ptr;
typedef t_counted_ptr< t_single_scenario_campaign_file_header > t_single_scenario_campaign_file_header_ptr;
typedef t_counted_ptr< t_multi_scenario_campaign_file_header > t_multi_scenario_campaign_file_header_ptr;

// --------------------------------------------------------------------------
// t_campaign_file_header_visitor class
// --------------------------------------------------------------------------

class t_campaign_file_header_visitor
{
public:
	// Member functions
	virtual void	visit( t_multi_scenario_campaign_file_header & header );
	virtual void	visit( t_multi_scenario_campaign_file_header const & header );
	virtual void	visit( t_single_scenario_campaign_file_header & header );
	virtual void	visit( t_single_scenario_campaign_file_header const & header );

protected:
	// Destructor
	~t_campaign_file_header_visitor() {}
};

// --------------------------------------------------------------------------
// t_campaign_file_header class
// --------------------------------------------------------------------------

class t_campaign_file_header : public t_counted_object, private t_uncopyable
{
public:
	// Types
	typedef t_campaign_file_header_visitor t_visitor;

	// Member functions
	virtual void						accept( t_visitor & visitor ) = 0;
	virtual void						accept( t_visitor & visitor ) const = 0;
	virtual int							get_map_count() const = 0;
	virtual std::streambuf::pos_type	get_map_data_end( int map_num ) const = 0;
	virtual std::streambuf::pos_type	get_map_data_start( int map_num ) const = 0;
	virtual t_map_header const &		get_map_header( int map_num ) const = 0;
	virtual std::string const &			get_name() const = 0;
	virtual bool						is_multi_scenario() const = 0;
};

// --------------------------------------------------------------------------
// t_single_scenario_campaign_file_header class
// --------------------------------------------------------------------------

class t_single_scenario_campaign_file_header : public t_campaign_file_header
{
public:
	// Constructor/Destructor
	t_single_scenario_campaign_file_header();
	virtual ~t_single_scenario_campaign_file_header();

	// Member functions
	virtual void						accept( t_visitor & visitor );
	virtual void						accept( t_visitor & visitor ) const;
	virtual int							get_map_count() const;
	virtual std::streambuf::pos_type	get_map_data_end( int map_num ) const;
	virtual std::streambuf::pos_type	get_map_data_start( int map_num ) const;
	t_map_header const &				get_map_header() const;
	virtual t_map_header const &		get_map_header( int map_num ) const;
	virtual std::string const &			get_name() const;
	virtual bool						is_multi_scenario() const;
	bool								read(
											std::streambuf &		stream,
											t_progress_handler *	progress_handler_ptr );
	void								set_map_header(
											t_map_header const &	new_map_header );

private:
	// Data members
	t_owned_ptr< t_map_header >	m_map_header_ptr;
	std::streambuf::pos_type	m_map_data_start;
	std::streambuf::pos_type	m_map_data_end;
};

// --------------------------------------------------------------------------
// t_single_scenario_campaign_file_header inline members
// --------------------------------------------------------------------------

// --------------------------------------------------------------------------
// --------------------------------------------------------------------------
inline t_map_header const &
t_single_scenario_campaign_file_header::get_map_header() const
{
	return *m_map_header_ptr;
}

// --------------------------------------------------------------------------
// t_multi_scenario_campaign_file_header class
// --------------------------------------------------------------------------

class t_multi_scenario_campaign_file_header : public t_campaign_file_header
{
public:
	// Constructor/Destructor
	virtual ~t_multi_scenario_campaign_file_header();

	// Member functions
	virtual void						accept( t_visitor & visitor );
	virtual void						accept( t_visitor & visitor ) const;
	virtual int							get_map_count() const;
	virtual std::streambuf::pos_type	get_map_data_end( int map_num ) const;
	virtual std::streambuf::pos_type	get_map_data_start( int map_num ) const;
	virtual t_map_header const &		get_map_header( int map_num ) const;
	std::string const &					get_description() const;
	virtual std::string const &			get_name() const;
	virtual bool						is_multi_scenario() const;
	bool								read(
											std::streambuf &		stream,
											t_progress_handler *	progress_handler_ptr );

private:
	// Types
	struct t_map_info
	{
		std::streambuf::pos_type		data_start;
		std::streambuf::pos_type		data_end;
		t_shared_ptr< t_map_header >	header_ptr;
	};

	// Data members
	std::string					m_name;
	std::string					m_description;
	std::vector< t_map_info >	m_map_info_vector;
};

// --------------------------------------------------------------------------
// Non-member functions
// --------------------------------------------------------------------------

// --------------------------------------------------------------------------
// --------------------------------------------------------------------------
t_campaign_file_header_ptr create_campaign_file_header(
	t_campaign_file_ref const &	file_ref,
	t_progress_handler *		progress_handler_ptr );

// --------------------------------------------------------------------------
// --------------------------------------------------------------------------
t_multi_scenario_campaign_file_header_ptr
create_multi_scenario_campaign_file_header(
	t_campaign_file_ref const &	file_ref,
	t_progress_handler *		progress_handler_ptr );

// --------------------------------------------------------------------------
// --------------------------------------------------------------------------
t_single_scenario_campaign_file_header_ptr
create_single_scenario_campaign_file_header(
	t_campaign_file_ref const &	file_ref,
	t_progress_handler *		progress_handler_ptr );

// --------------------------------------------------------------------------
// --------------------------------------------------------------------------
std::auto_ptr< std::streambuf > open_campaign_file(
	t_campaign_file_ref const &	file_ref );

#endif // !defined( CAMPAIGN_FILE_HEADER_H_INCLUDED )
